/**
 * API测试脚本
 * 用于测试不同的API基础URL和参数组合
 */

import http from 'http';
import https from 'https';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { apiLogger } from './apiLogger.js';

// 获取当前文件目录
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// 启用API日志记录
const ENABLE_API_LOGGING = process.argv.includes('--log-api');
const CLEAR_API_LOGS = process.argv.includes('--clear-api-logs');

// 日志记录设置
console.log(`API日志记录状态: ${ENABLE_API_LOGGING ? '已启用' : '已禁用'}`);
apiLogger.setEnabled(ENABLE_API_LOGGING);

// 清除API日志（如果指定）
if (CLEAR_API_LOGS) {
    apiLogger.clearLogs();
    console.log('API日志已清除');
}

// 加载配置文件
const loadConfig = () => {
    const configPath = path.resolve(__dirname, './env.config');

    if (!fs.existsSync(configPath)) {
        console.error('错误：找不到配置文件', configPath);
        process.exit(1);
    }

    try {
        console.log('正在加载配置文件...');
        const config = {};
        const content = fs.readFileSync(configPath, 'utf8');

        // 解析配置文件中的键值对
        content.split('\n').forEach(line => {
            // 跳过注释和空行
            if (line.trim().startsWith('#') || !line.trim()) return;

            // 提取键值对
            const match = line.match(/^([A-Z0-9_]+)="([^"]*)"/);
            if (match) {
                const [, key, value] = match;
                config[key] = value;

                // 处理特殊情况，如引用其他变量
                if (value.includes('${')) {
                    const refMatch = value.match(/\${([^}]*)}/);
                    if (refMatch && config[refMatch[1]]) {
                        config[key] = value.replace(/\${[^}]*}/, config[refMatch[1]]);
                    }
                }
            }
        });

        console.log('配置文件加载成功');
        return config;
    } catch (error) {
        console.error('加载配置文件失败:', error);
        process.exit(1);
    }
};

const CONFIG = loadConfig();

// 测试配置
const API_CONFIGURATIONS = [
    {
        name: '配置1 - 原始配置',
        baseUrl: CONFIG.AUTO_API_BASE_URL,
        projectId: CONFIG.PROJECT_ID,
        schema: CONFIG.SCHEMA_NAME
    },
    {
        name: '配置2 - 使用相同schema',
        baseUrl: CONFIG.AUTO_API_BASE_URL,
        projectId: CONFIG.PROJECT_ID,
        schema: CONFIG.SCHEMA_NAME
    },
    {
        name: '配置3 - 不使用端口',
        baseUrl: CONFIG.AUTO_API_BASE_URL.replace(/:\d+/, ''),
        projectId: CONFIG.PROJECT_ID,
        schema: CONFIG.SCHEMA_NAME
    },
    {
        name: '配置4 - 使用alternative-api路径',
        baseUrl: CONFIG.AUTO_API_BASE_URL.replace(/\/autoapi$/, '/alternative-api'),
        projectId: CONFIG.PROJECT_ID,
        schema: CONFIG.SCHEMA_NAME
    },
    {
        name: '配置5 - 简化路径',
        baseUrl: new URL(CONFIG.AUTO_API_BASE_URL).origin + '/api',
        projectId: CONFIG.PROJECT_ID,
        schema: CONFIG.SCHEMA_NAME
    }
];

// 测试用的API路径和请求参数
const API_TESTS = [
    {
        name: 'getToken测试',
        endpoint: '/get_token',
        method: 'POST',
        getBody: (config) => ({ project_id: config.projectId }),
        handler: (data) => {
            console.log(`Token: ${data.data?.token || 'Not found'}`);
            return data.data?.token;
        }
    },
    {
        name: 'findTableSchema测试',
        endpoint: '/findby?tbName=findbytableSchema',
        method: 'POST',
        getBody: (config) => ({ tablelist: { tableSchema: config.schema } }),
        handler: (data) => {
            if (Array.isArray(data)) {
                console.log(`找到 ${data.length} 个表`);
                if (data.length > 0) {
                    console.log('示例表:', data.slice(0, 3));
                }
            } else {
                console.log('返回数据格式不正确:', data);
            }
            return data;
        }
    },
    {
        name: 'findTableList测试',
        endpoint: '/findtablelist',
        method: 'POST',
        getBody: (config) => ({ schema: config.schema }),
        handler: (data) => {
            console.log('表列表数据:', data);
            return data;
        }
    },
    {
        name: 'findDbMeta测试',
        endpoint: '/finddbmeta',
        method: 'POST',
        getBody: (config) => ({ schema: config.schema, type: 'tables' }),
        handler: (data) => {
            console.log('数据库元数据:', data);
            return data;
        }
    }
];

// 输出目录
const OUTPUT_DIR = path.resolve(__dirname, '../raw-data/api-test');
if (!fs.existsSync(OUTPUT_DIR)) {
    fs.mkdirSync(OUTPUT_DIR, { recursive: true });
    console.log(`创建输出目录: ${OUTPUT_DIR}`);
}

/**
 * 发送HTTP/HTTPS请求
 */
async function fetchApi(url, method, body, headers = {}) {
    console.log(`发起API请求: ${method} ${url}`);
    console.log(`请求体: ${JSON.stringify(body)}`);

    // 记录API请求
    const requestId = apiLogger.logRequest(method, url, headers, body);

    return new Promise((resolve, reject) => {
        try {
            // 解析URL
            const urlObj = new URL(url);

            // 超时时间
            const timeout = 10000; // 10秒

            // 请求选项
            const options = {
                hostname: urlObj.hostname,
                port: urlObj.port || (urlObj.protocol === 'https:' ? 443 : 80),
                path: urlObj.pathname + urlObj.search,
                method: method,
                headers: {
                    'Content-Type': 'application/json',
                    ...headers
                },
                timeout: timeout
            };

            // 选择HTTP或HTTPS
            const client = urlObj.protocol === 'https:' ? https : http;

            // 创建请求
            const req = client.request(options, (res) => {
                let data = '';

                // 接收数据
                res.on('data', (chunk) => {
                    data += chunk;
                });

                // 数据接收完成
                res.on('end', () => {
                    try {
                        console.log(`收到响应: 状态码 ${res.statusCode}`);

                        let parsedData = null;
                        let errorMsg = null;

                        // 尝试解析JSON
                        try {
                            parsedData = JSON.parse(data);
                            console.log(`响应数据摘要: ${JSON.stringify(parsedData).substring(0, 200)}...`);
                        } catch (e) {
                            errorMsg = e.message;
                            console.log(`响应不是有效的JSON: ${data.substring(0, 100)}...`);
                        }

                        // 记录API响应
                        apiLogger.logResponse(
                            requestId,
                            res.statusCode,
                            res.headers,
                            parsedData || data,
                            errorMsg ? new Error(errorMsg) : null
                        );

                        if (res.statusCode >= 200 && res.statusCode < 300) {
                            if (parsedData) {
                                resolve({
                                    status: res.statusCode,
                                    data: parsedData,
                                    headers: res.headers,
                                    rawData: data
                                });
                            } else {
                                resolve({
                                    status: res.statusCode,
                                    data: null,
                                    error: errorMsg,
                                    headers: res.headers,
                                    rawData: data
                                });
                            }
                        } else {
                            console.log(`错误状态码: ${res.statusCode}`);
                            console.log(`响应数据: ${data.substring(0, 100)}...`);
                            resolve({
                                status: res.statusCode,
                                data: null,
                                headers: res.headers,
                                rawData: data
                            });
                        }
                    } catch (e) {
                        // 记录处理响应失败的错误
                        apiLogger.logResponse(requestId, res.statusCode, res.headers, data, e);
                        reject(new Error(`处理响应失败: ${e.message}`));
                    }
                });
            });

            // 处理错误
            req.on('error', (e) => {
                console.error(`请求错误: ${e.message}`);
                // 记录请求错误
                apiLogger.logResponse(requestId, 0, null, null, e);
                reject(new Error(`请求失败: ${e.message}`));
            });

            // 处理超时
            req.on('timeout', () => {
                console.error(`请求超时: ${timeout}ms`);
                // 记录请求超时
                apiLogger.logResponse(requestId, 0, null, null, new Error(`请求超时: ${timeout}ms`));
                req.destroy();
                reject(new Error(`请求超时: ${timeout}ms`));
            });

            // 发送请求体
            if (body) {
                req.write(JSON.stringify(body));
            }

            req.end();
        } catch (e) {
            // 记录创建请求失败的错误
            apiLogger.logResponse(requestId, 0, null, null, e);
            reject(new Error(`创建请求失败: ${e.message}`));
        }
    });
}

/**
 * 测试单个API配置
 */
async function testApiConfiguration(config) {
    console.log(`\n========== 开始测试 ${config.name} ==========`);
    console.log(`基础URL: ${config.baseUrl}`);
    console.log(`项目ID: ${config.projectId}`);
    console.log(`Schema: ${config.schema}`);

    const results = {
        config: config,
        timestamp: new Date().toISOString(),
        tests: []
    };

    let token = null;

    // 执行API测试
    for (const test of API_TESTS) {
        try {
            console.log(`\n----- 执行 ${test.name} -----`);

            // 构造完整URL
            const url = `${config.baseUrl}${test.endpoint}`;

            // 准备请求体
            const body = test.getBody(config);

            // 准备请求头
            const headers = {};
            if (token && test.name !== 'getToken测试') {
                headers['Authorization'] = token;
            }

            // 发送请求
            const response = await fetchApi(url, test.method, body, headers);

            // 处理结果
            let handlerResult = null;
            let success = false;

            try {
                if (response.status >= 200 && response.status < 300 && response.data) {
                    handlerResult = test.handler(response.data);
                    success = true;

                    // 如果是获取token测试，保存token用于后续请求
                    if (test.name === 'getToken测试' && handlerResult) {
                        token = handlerResult;
                    }
                } else {
                    console.log(`测试失败: 状态码 ${response.status}`);
                }
            } catch (handlerError) {
                console.error(`处理响应结果失败: ${handlerError.message}`);
            }

            // 记录测试结果
            results.tests.push({
                name: test.name,
                url: url,
                method: test.method,
                body: body,
                status: response.status,
                success: success,
                timestamp: new Date().toISOString(),
                response: {
                    status: response.status,
                    headers: response.headers,
                    data: response.data,
                    rawDataPreview: response.rawData ? response.rawData.substring(0, 500) : null
                }
            });

        } catch (error) {
            console.error(`测试 ${test.name} 失败: ${error.message}`);

            // 记录错误
            results.tests.push({
                name: test.name,
                error: error.message,
                success: false,
                timestamp: new Date().toISOString()
            });
        }
    }

    // 保存测试结果
    const fileName = `${config.name.replace(/\s+/g, '_').toLowerCase()}_results.json`;
    const filePath = path.join(OUTPUT_DIR, fileName);

    fs.writeFileSync(filePath, JSON.stringify(results, null, 2));
    console.log(`\n测试结果已保存到: ${filePath}`);

    return results;
}

/**
 * 主函数 - 测试所有API配置
 */
async function main() {
    console.log('===== 开始API测试 =====');
    console.log(`测试时间: ${new Date().toISOString()}`);
    console.log(`测试配置数量: ${API_CONFIGURATIONS.length}`);
    console.log(`测试API数量: ${API_TESTS.length}`);

    const allResults = [];

    for (const config of API_CONFIGURATIONS) {
        try {
            const result = await testApiConfiguration(config);
            allResults.push(result);
        } catch (error) {
            console.error(`测试配置 ${config.name} 失败: ${error.message}`);
        }
    }

    // 生成测试汇总
    const summary = {
        timestamp: new Date().toISOString(),
        totalConfigurations: API_CONFIGURATIONS.length,
        totalTests: API_CONFIGURATIONS.length * API_TESTS.length,
        configurations: allResults.map(result => ({
            name: result.config.name,
            baseUrl: result.config.baseUrl,
            successCount: result.tests.filter(t => t.success).length,
            totalTests: result.tests.length
        }))
    };

    fs.writeFileSync(
        path.join(OUTPUT_DIR, 'test_summary.json'),
        JSON.stringify(summary, null, 2)
    );

    // 生成HTML报告
    const htmlReport = generateHtmlReport(summary, allResults);
    fs.writeFileSync(
        path.join(OUTPUT_DIR, 'test_report.html'),
        htmlReport
    );

    console.log('\n===== API测试完成 =====');
    console.log(`共测试 ${API_CONFIGURATIONS.length} 个配置`);
    console.log(`每个配置测试 ${API_TESTS.length} 个API`);
    console.log(`测试结果已保存到: ${OUTPUT_DIR}`);
    console.log(`HTML报告: ${path.join(OUTPUT_DIR, 'test_report.html')}`);

    // 找出最成功的配置
    const mostSuccessfulConfig = [...summary.configurations].sort((a, b) => b.successCount - a.successCount)[0];
    console.log(`\n最成功的配置: ${mostSuccessfulConfig.name}`);
    console.log(`成功率: ${mostSuccessfulConfig.successCount}/${mostSuccessfulConfig.totalTests}`);
    console.log(`基础URL: ${mostSuccessfulConfig.baseUrl}`);
}

/**
 * 生成HTML测试报告
 */
function generateHtmlReport(summary, allResults) {
    const html = `<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>API测试报告</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 0; padding: 20px; color: #333; }
        h1, h2, h3 { color: #1a73e8; }
        .summary { background-color: #f5f5f5; padding: 15px; border-radius: 5px; margin-bottom: 20px; }
        .config { margin-bottom: 30px; border: 1px solid #ddd; border-radius: 5px; overflow: hidden; }
        .config-header { background-color: #1a73e8; color: white; padding: 10px 15px; }
        .config-body { padding: 15px; }
        .test { margin-bottom: 15px; border: 1px solid #ddd; border-radius: 5px; overflow: hidden; }
        .test-header { padding: 10px 15px; display: flex; justify-content: space-between; }
        .success { background-color: #d4edda; }
        .failure { background-color: #f8d7da; }
        .test-body { padding: 0 15px 15px; }
        pre { background-color: #f5f5f5; padding: 10px; border-radius: 5px; overflow-x: auto; }
        .badge { padding: 3px 8px; border-radius: 3px; font-size: 12px; }
        .badge-success { background-color: #28a745; color: white; }
        .badge-danger { background-color: #dc3545; color: white; }
        .badge-info { background-color: #17a2b8; color: white; }
        table { width: 100%; border-collapse: collapse; }
        th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }
        th { background-color: #f2f2f2; }
        .collapsible { cursor: pointer; }
        .content { display: none; }
        .show { display: block; }
    </style>
</head>
<body>
    <h1>API测试报告</h1>
    <div class="summary">
        <h2>测试汇总</h2>
        <p>测试时间: ${summary.timestamp}</p>
        <p>总测试配置数: ${summary.totalConfigurations}</p>
        <p>总测试API数: ${summary.totalTests}</p>
        
        <h3>配置成功率</h3>
        <table>
            <tr>
                <th>配置名称</th>
                <th>基础URL</th>
                <th>成功/总计</th>
                <th>成功率</th>
            </tr>
            ${summary.configurations.map(config => `
            <tr>
                <td>${config.name}</td>
                <td>${config.baseUrl}</td>
                <td>${config.successCount}/${config.totalTests}</td>
                <td><span class="badge ${config.successCount > 0 ? 'badge-success' : 'badge-danger'}">${Math.round(config.successCount / config.totalTests * 100)}%</span></td>
            </tr>
            `).join('')}
        </table>
    </div>
    
    ${allResults.map(result => `
    <div class="config">
        <div class="config-header">
            <h2>${result.config.name}</h2>
        </div>
        <div class="config-body">
            <p>基础URL: ${result.config.baseUrl}</p>
            <p>项目ID: ${result.config.projectId}</p>
            <p>Schema: ${result.config.schema}</p>
            <p>成功测试: ${result.tests.filter(t => t.success).length}/${result.tests.length}</p>
            
            <h3>API测试结果</h3>
            ${result.tests.map(test => `
            <div class="test">
                <div class="test-header ${test.success ? 'success' : 'failure'}">
                    <h4>${test.name}</h4>
                    <span class="badge ${test.success ? 'badge-success' : 'badge-danger'}">${test.success ? '成功' : '失败'}</span>
                </div>
                <div class="test-body">
                    ${test.error ? `<p>错误: ${test.error}</p>` : ''}
                    ${test.url ? `
                    <p>URL: ${test.url}</p>
                    <p>方法: ${test.method}</p>
                    
                    <div class="collapsible">请求体 <span class="badge badge-info">显示/隐藏</span></div>
                    <div class="content">
                        <pre>${JSON.stringify(test.body, null, 2)}</pre>
                    </div>
                    
                    <div class="collapsible">响应 <span class="badge badge-info">显示/隐藏</span></div>
                    <div class="content">
                        <p>状态码: ${test.response?.status || 'N/A'}</p>
                        <pre>${test.response?.rawDataPreview ? test.response.rawDataPreview.replace(/</g, '&lt;').replace(/>/g, '&gt;') : 'No data'}</pre>
                    </div>
                    ` : ''}
                </div>
            </div>
            `).join('')}
        </div>
    </div>
    `).join('')}

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            var coll = document.getElementsByClassName("collapsible");
            for (var i = 0; i < coll.length; i++) {
                coll[i].addEventListener("click", function() {
                    this.classList.toggle("active");
                    var content = this.nextElementSibling;
                    if (content.classList.contains("show")) {
                        content.classList.remove("show");
                    } else {
                        content.classList.add("show");
                    }
                });
            }
        });
    </script>
</body>
</html>`;

    return html;
}

// 执行主函数
main().catch(error => {
    console.error('测试失败:', error);
    process.exit(1);
}); 